﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Reflection;
using System.Diagnostics;
using ExpressionEvaluator;
using System.Xml.Linq;
using System.Runtime.Serialization;
using System.Xml;
using WCFCollection;

namespace RemoteLinqBase.ClientBase
{
	public class ClientQueryProvider : IQueryProvider
	{
		private Type _Type;
		public ClientQueryProvider(Type type)
		{
			_Type = type;
		}

		IQueryable<S> IQueryProvider.CreateQuery<S>(Expression expression)
		{
			return new ClientQuery<S>(this, expression);
		}

		IQueryable IQueryProvider.CreateQuery(Expression expression)
		{
			Type elementType = LinqTools.GetElementType(expression.Type);
			try
			{
				return (IQueryable)Activator.CreateInstance(typeof(ClientQuery<>).MakeGenericType(elementType), new object[] { this, expression });
			}
			catch (TargetInvocationException tie)
			{
				throw tie.InnerException;
			}
		}

		S IQueryProvider.Execute<S>(Expression expression)
		{
			return (S)this.Execute(expression);
		}

		object IQueryProvider.Execute(Expression expression)
		{
			return this.Execute(expression);
		}

		public object Execute(Expression expression)
		{
			//LinqTools.Evalizer.AddLookupTypes(RepositoryFactory.GetRegisteredTypes());

			string linq = "linq" + LinqTools.Evalizer.EvalizeExpression(expression);
			Type resultType = expression.Type;
			// if queryable result, then result type is ienumerable
			if (resultType.GetInterface(typeof(IQueryable).FullName) != null)
			{
				resultType = typeof(IEnumerable<>).MakeGenericType(resultType.GetGenericArguments());
			}
			XElement result = CollectionsFactory.GetCollection(_Type).GetLinqResult(linq);

            return SerializationTool.ToObject(resultType, result);
		}

	}
}
